/*
 * @Description: 
 * @Author: chenjiaxin
 * @Date: 2021-12-21 21:02:22
 * @LastEditTime: 2022-01-05 21:10:34
 * @FilePath: \novel-serve\src\middleware\auth.middleware.js
 */
const jwt = require('jsonwebtoken');
const errorTypes = require("../constants/error-types");
const service = require("../service/user.service");
const md5Password = require('../utils/password-handle');
const { PUBLIC_KEY } = require("../app/config");
const { verifyEmail } = require("../utils/verify-handle");


const verifyLogin = async (ctx, next) => {
  try {
    // 1、获取客户端用户名，和密码
    let { e_mail, password } = ctx.request.body;
    // 2、校验参数
    if (!e_mail || !password) {
      // const error = new Error(errorTypes.REGISTER_IS_REQUIRED);
      //发射一个错误信息
      return ctx.app.emit('error', errorTypes.REGISTER_IS_REQUIRED, ctx);
    }

    //校验邮箱
    if (!verifyEmail(e_mail)) {
      // const error = new Error(errorTypes.E_MAIL_ERROR);
      return ctx.app.emit('error', errorTypes.E_MAIL_ERROR, ctx);
    }

    //3、判断用户有没有
    let user = await service.getUserByEmail(e_mail);
    if (!user) {
      // const error = new Error(errorTypes.USER_DOES_NOT_EXIST);
      return ctx.app.emit('error', errorTypes.USER_DOES_NOT_EXIST, ctx);

    }

    // 4、有这个用户，在判断用户的密码是否一致
    password = md5Password(password);
    if (password != user.password) {
      //密码错误
      // const error = new Error(errorTypes.PASSWORD_WRONG);
      return ctx.app.emit('error', errorTypes.PASSWORD_WRONG, ctx);
    }

    ctx.user = user;
    await next();

  } catch (error) {
    console.log(error);
    return ctx.app.emit('error', errorTypes.SYNTAX_ERROR, ctx, error.message);
  }
}

/**
 * 验证token
 * @param {*} ctx 
 * @param {*} next 
 * @returns 
 */
const verifyAuth = async (ctx, next) => {
  try {
    // console.log(ctx.headers.token)
    // 1、先拿到客户端传过来的 token。postman是用的 authorization 字段，axios请求传的是token字段
    let token = ctx.headers.token || ctx.headers.authorization;
    if (!token) {
      return ctx.app.emit('error', errorTypes.NO_TOKEN, ctx, 'token不能为空');
    }
    token = token.includes('Bearer ') ? token.replace("Bearer ", "") : token;

    // console.log(token);
    
    try {
      // 2、校验token。result 是还原了颁发token时的 内容 {id: 1, e_mail: xxx }, 里面还有其他字段,token,和有效期
      const result = jwt.verify(token, PUBLIC_KEY, {
        algorithms: ["RS256"]
      });
      console.log("成功了===");
      ctx.user = result;
      await next();
    } catch (error) {

      // console.log(error);
      ctx.app.emit('error', errorTypes.TOKEN_INVALID, ctx, error.message);
    }

  } catch (error) {
    // console.log(error);
    ctx.app.emit('error', errorTypes.SYNTAX_ERROR, ctx, error.message);
  }



}

const verifyLoginCode = async (ctx, next) => {
  try {
    let { e_mail, code } = ctx.request.body;
    //1、校验邮箱格式
    if (!verifyEmail(e_mail)) {
      return ctx.app.emit('error', errorTypes.E_MAIL_ERROR, ctx);
    }

    console.log("session值===", ctx.session);
    let targetEmail = ctx.session?.emailInfo?.e_mail;
    let targetCode = ctx.session?.emailInfo?.code;
    //2、验证登录邮箱 是否 和接受验证码的邮箱一直
    if (!targetCode) {
      
      return ctx.app.emit('error', errorTypes.CODE_LOGIN_ERROR, ctx, "请先获取邮箱验证码");
    }
    if (e_mail !== targetEmail) {
      return ctx.app.emit('error', errorTypes.LOGIN_CODE_EMAIL_UNEQUAL, ctx);
    }

    if (code !== targetCode) {
      return ctx.app.emit('error', errorTypes.CODE_ERROR, ctx);
    }

    //3、判断用户有没有
    let user = await service.getUserByEmail(e_mail);
    if (!user) {
      // const error = new Error(errorTypes.USER_DOES_NOT_EXIST);
      return ctx.app.emit('error', errorTypes.USER_DOES_NOT_EXIST, ctx);

    }
    ctx.user = user;

    await next();

  } catch (error) {
    console.log(error);
    return ctx.app.emit("error", errorTypes.SYNTAX_ERROR, ctx, error.message);
  }
}



module.exports = {
  verifyLogin,
  verifyAuth,
  verifyLoginCode
}
